package view;
import gui.CardContainer;
import gui.Chat;
import gui.Seat;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import model.Action;
import model.CardInterface;
import model.ChosenAction;
import model.UserInterface;
import toolkit.Parse;
import data.GameInterface;
import data.SeatInterface;
import data.SessionInterface;

// TODO: Auto-generated Javadoc
/**
 * This code was edited or generated using CloudGarden's Jigloo
 * SWT/Swing GUI Builder, which is free for non-commercial
 * use. If Jigloo is being used commercially (ie, by a corporation,
 * company or business for any purpose whatever) then you
 * should purchase a license for each developer using Jigloo.
 * Please visit www.cloudgarden.com for details.
 * Use of Jigloo implies acceptance of these licensing terms.
 * A COMMERCIAL LICENSE HAS NOT BEEN PURCHASED FOR
 * THIS MACHINE, SO JIGLOO OR THIS CODE CANNOT BE USED
 * LEGALLY FOR ANY CORPORATE OR COMMERCIAL PURPOSE.
 */
public class Table extends View {

	private gui.PlayTable playTable;
	
	private JButton buttonCall;
	
	private JLabel labelBet;

	private JButton buttonRaise;
	
	private JButton buttonFold;
	
	private JSlider sliderBet;
	
	private Chat textChat;
	
	private JProgressBar progressTime;
	
	private JPanel panelControls;
	
	private JPanel panelControlsContainer;
	
	private JPanel panelControlsFrame;
	
	protected controller.Table controller;
	
	private JButton buttonStats;

	private CardContainer panelHand;
	
	private JButton buttonSend;
	
	private JTextField inputChat;

	private GameInterface gameData;
	
	private ArrayList<Seat> seats;
	
	private Timer turnTimer;
    
	private int intervalCounter;
	
	private static final int TURN_TIMER_SPEED = 250;
	
	private Action action;
	
	private Thread currentThread;
	
	/**
	 * Auto-generated main method to display this
	 * JPanel inside a new JFrame.
	 * 
	 * @param args the args
	 */
	public static void main(String[] args) {
		JFrame frame = new JFrame();
		frame.getContentPane().add(new Table());
		frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		frame.pack();
		frame.setVisible(true);
	}
	
	/**
	 * Instantiates a new table.
	 */
	public Table() {
		super();
		initGUI();
	}
	
	public Table(controller.Table controller, GameInterface gameData) {
		this();
		this.controller = controller;
		this.gameData = gameData;
	}
	
	/**
	 * Inits the gui.
	 */
	private void initGUI() {
		try {
			BorderLayout thisLayout = new BorderLayout();
			this.setLayout(thisLayout);
			this.setPreferredSize(new java.awt.Dimension(717, 620));
			{
				panelControlsContainer = new JPanel();
				this.add(panelControlsContainer, BorderLayout.SOUTH);
				{
					panelControls = new JPanel();
					panelControlsContainer.add(panelControls, BorderLayout.CENTER);
					panelControls.setPreferredSize(new java.awt.Dimension(717, 198));
					panelControls.setSize(717, 198);
					panelControls.setLayout(null);
					{
						buttonRaise = new JButton();
						panelControls.add(buttonRaise);
						buttonRaise.setBounds(12, 40, 128, 21);
						buttonRaise.setText("Raise");
						buttonRaise.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent evt) {
								buttonRaiseActionPerformed(evt);
							}
						});
					}
					{
						progressTime = new JProgressBar();
						panelControls.add(progressTime);
						progressTime.setBounds(152, 172, 386, 14);
					}
					{
						textChat = new Chat();
						panelControls.add(textChat);
						textChat.setBounds(152, 12, 386, 127);
					}
					{
						sliderBet = new JSlider();
						panelControls.add(sliderBet);
						sliderBet.setValue(0);
						sliderBet.setBounds(550, 12, 115, 16);
					}
					{
						buttonCall = new JButton();
						panelControls.add(buttonCall);
						buttonCall.setBounds(12, 12, 128, 21);
						buttonCall.setText("Call");
						buttonCall.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent evt) {
								buttonCallActionPerformed(evt);
							}
						});
					}
					{
						buttonFold = new JButton();
						panelControls.add(buttonFold);
						buttonFold.setBounds(12, 67, 128, 21);
						buttonFold.setText("Fold");
						buttonFold.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent evt) {
								buttonFoldActionPerformed(evt);
							}
						});
					}
					{
						labelBet = new JLabel();
						panelControls.add(labelBet);
						labelBet.setBounds(672, 13, 37, 15);
					}
					{
						buttonSend = new JButton();
						panelControls.add(buttonSend);
						buttonSend.setBounds(464, 145, 74, 21);
						buttonSend.setText("Send");
						buttonSend.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent evt) {
								buttonSendActionPerformed(evt);
							}
						});
					}
					{
						inputChat = new JTextField();
						panelControls.add(inputChat);
						inputChat.setBounds(152, 145, 306, 21);
					}
					{
						buttonStats = new JButton();
						panelControls.add(buttonStats);
						buttonStats.setBounds(12, 145, 128, 21);
						buttonStats.setText("Statistics");
						buttonStats.setEnabled(false);
						buttonStats.addActionListener(new ActionListener() {
							public void actionPerformed(ActionEvent evt) {
								buttonStatsActionPerformed(evt);
							}
						});
					}
					{
						panelHand = new CardContainer();
						panelControls.add(panelHand);
						panelHand.setBounds(550, 34, 157, 132);
					}
				}
				this.setDefaultButton(buttonSend);
			}
			{
				playTable = new gui.PlayTable();
				this.add(playTable, BorderLayout.CENTER);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void postInitGUI()
	{
		frame.setResizable(true);
		
		frame.addWindowListener(new WindowAdapter()
		{
			public void windowClosed(WindowEvent e)
			{
				controller.leaveGame();
			}
		});
		
		playTable.setPositions(gameData.getSeats());
		playTable.prepareLayout();
		
		seats = playTable.getSeats();
		
		MouseListener mouseListener = new MouseAdapter()
		{
			public void mouseReleased(MouseEvent e)
			{
				Object source = e.getSource();
				
				if (source instanceof Seat)
				{
					Seat seat = (Seat) source;
					
					if (!seat.isTaken())
					{
						controller.join(seats.indexOf(seat));
					}
				}
			}
		};
		
		for (Seat seat: seats)
		{
			seat.addMouseListener(mouseListener);
		}
		
		setUserInterfaceEnabled(false);
		
		sliderBet.addChangeListener(new ChangeListener()
	    {
	    	public void stateChanged(ChangeEvent e)
	    	{
	    		String value = Parse.toString(sliderBet.getValue());
	    		
	    		labelBet.setText(value);
	    		
	    		buttonCall.setText("Call " + value);
	    		
	    		buttonRaise.setText("Raise " + value);
	    	}
	    });
		
		turnTimer = new Timer(TURN_TIMER_SPEED, new ActionListener()
		{
			public void actionPerformed(ActionEvent e)
			{
				if (e.getSource() == turnTimer)
				{
					progressTime.setValue(++intervalCounter * TURN_TIMER_SPEED);
				}
			}
		});
	}
	
	public void enableStatistics()
	{
		buttonStats.setEnabled(true);
	}
	
	public ChosenAction chooseAction()
	{
		currentThread = Thread.currentThread();
		
		EventQueue.invokeLater(startTurn);
		
		try
		{
			Thread.sleep(30 * 1000);
			
			action = Action.FOLD;
		}
		catch (InterruptedException e)
		{
			
		}

		EventQueue.invokeLater(endTurn);
		
		ChosenAction chosenAction = new ChosenAction(action);
		
		if (action == Action.RAISE)
		{
			chosenAction.setAmountRaised(sliderBet.getValue());
		}
		
		return chosenAction;
	}
	
	public void setTurnSeatIndex(int seatIndex)
	{
		int seatsSize = seats.size();
		
		for (int i = 0; i < seatsSize; i++)
		{
			seats.get(i).setTurn(i == seatIndex);
		}
	}
	
	private Runnable startTurn = new Runnable()
	{
		public void run()
		{
			turnTimer.start();
			
			sliderBet.setMinimum(20);
			sliderBet.setMaximum(1000);
			
			progressTime.setMaximum(30 * 1000);
			
			setUserInterfaceEnabled(true);
		}
	};

	private Runnable endTurn = new Runnable()
	{
		public void run()
		{
			turnTimer.stop();
			
			intervalCounter = 0;
			
			progressTime.setValue(0);
			
			setUserInterfaceEnabled(false);
		}
	};
	
	public void updateSession(SessionInterface session)
	{
		updateBoard(session.getBoardCards());
		
		int seatsSize = seats.size();
		
		for (int i = 0; i < seatsSize; i++)
		{
			updateSeat(session.getSeat(i));
		}
	}
	
	private SeatInterface seat;
	
	public void updateSeat(SeatInterface seat)
	{
		if (seat != null)
		{
			this.seat = seat;
			
			EventQueue.invokeLater(updateSeat);
		}
	}
	
	private Runnable updateSeat = new Runnable()
	{
		public void run()
		{
			seats.get(seat.getIndex()).updateData(seat);
			
			repaint();
		}
	};
	
	public void sendChatMessage(UserInterface user, String message)
	{
		textChat.appendLine(user.getUsername(), message);
	}
	
	public void updateBoard(ArrayList<CardInterface> cards)
	{
		playTable.setBoardCards(cards);
	}

	public void updateHand(ArrayList<CardInterface> cards)
	{
		panelHand.setCards(cards);
	}
	
	public void setUserInterfaceEnabled(boolean enabled)
	{
		JComponent[] buttons = {buttonCall, buttonRaise, buttonFold, sliderBet};
		
		for (JComponent button: buttons)
		{
			button.setEnabled(enabled);
		}
	}
	
	private void buttonCallActionPerformed(ActionEvent e)
	{
		actionChosen(Action.CALL);
	}
	
	private void buttonRaiseActionPerformed(ActionEvent e)
	{
		actionChosen(Action.RAISE);
	}
	
	private void buttonFoldActionPerformed(ActionEvent e)
	{
		actionChosen(Action.FOLD);
	}
	
	private void buttonStatsActionPerformed(ActionEvent e)
	{
		controller.statistics();
	}

	private void buttonSendActionPerformed(ActionEvent e)
	{
		controller.sendChatMessage(inputChat.getText());
		inputChat.setText("");
	}
	
	public void actionChosen(Action action)
	{
		this.action = action;
		
		if (currentThread != null)
		{
			currentThread.interrupt();
			
			currentThread = null;
		}
	}
	
	/**
	* This method should return an instance of this class which does 
	* NOT initialize it's GUI elements. This method is ONLY required by
	* Jigloo if the superclass of this class is abstract or non-public. It 
	* is not needed in any other situation.
	 */
	public static Object getGUIBuilderInstance() {
		return new Table(Boolean.FALSE);
	}
	
	/**
	 * This constructor is used by the getGUIBuilderInstance method to
	 * provide an instance of this class which has not had it's GUI elements
	 * initialized (ie, initGUI is not called in this constructor).
	 */
	public Table(Boolean initGUI) {
		super();
	}
}
